package com.mashibing.juc.c_004;

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * @ClassName T02_AtomicVsSyncVsLongAdder
 * @Description 比较三种数据递增计数api AtomicInteger  Synchronized LongAdder
 * @Author xiongwei.wu
 * @Date 2021/7/1 15:33
 **/
public class T02_AtomicVsSyncVsLongAdder {
    static long count1 = 0l;
    static AtomicLong count2 = new AtomicLong(0);
    static LongAdder count3 = new LongAdder();

    public static void main(String[] args) {
        T02_AtomicVsSyncVsLongAdder t = new T02_AtomicVsSyncVsLongAdder();
        Thread[] threads = new Thread[1000];
        t.synchronizedLong(threads);
        t.atomicLong(threads);
        t.longAdder(threads);
    }

    void atomicLong(Thread[] threads) {
        for (int i = 0; i < threads.length; i++) {
            threads[i] =
                    new Thread(() -> {
                        for (int j = 0; j < 100000; j++) {
                            count2.incrementAndGet();
                        }
                    });
        }
        long start = System.currentTimeMillis();
        for (Thread thread : threads) {
            thread.start();
        }
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("Atomic: " + count2.get() + " time: " + (end - start));
    }

    void synchronizedLong(Thread[] threads) {
        Object lock = new Object();
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 100000; j++) {
                        synchronized (lock) {
                            count1++;
                        }
                    }
                }
            });
        }

        long start = System.currentTimeMillis();
        for (Thread thread : threads) thread.start();
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("Sync long: " + count1 + " time: " + (end - start));
    }

    void longAdder(Thread[] threads) {
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 100000; j++) {
                    count3.increment();
                }
            });
        }
        long start = System.currentTimeMillis();
        for (Thread thread : threads) thread.start();
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("LongAdder : " + count3 + " time: " + (end - start));
    }

}
